<?php

// ------------------------------------------------------------------------
// |@Author       : Jarmin <edshop@qq.com>
// |@----------------------------------------------------------------------
// |@Date         : 2025-04-06 22:45:54
// |@----------------------------------------------------------------------
// |@LastEditTime : 2025-04-21 13:12:58
// |@----------------------------------------------------------------------
// |@LastEditors  : Jarmin <jarmin@ladmin.cn>
// |@----------------------------------------------------------------------
// |@Description  : API版本控制中间件
// |@----------------------------------------------------------------------
// |@FilePath     : ApiVersionMiddleware.php
// |@----------------------------------------------------------------------
// |@Copyright (c) 2025 http://www.ladmin.cn   All rights reserved.
// ------------------------------------------------------------------------
declare (strict_types=1);

namespace think\admin\middleware;

use think\Response;

/**
 * API版本控制中间件
 *
 * 功能说明：
 * 1. 检查请求中是否包含有效的API版本号
 * 2. 验证API版本是否在允许的版本列表中
 * 3. 检查API版本是否已过期
 * 4. 处理API版本废弃情况
 */
class ApiVersionMiddleware
{
    /**
     * 中间件处理入口
     *
     * @param mixed $request 请求对象
     * @param \Closure $next 下一个中间件闭包
     * @return Response
     */
    public function handle($request, \Closure $next)
    {
        // 获取版本配置信息
        $versionSource = config('api.version_source', 'header');
        $versionParam = config('api.version_param', 'x-api-version');
        $version = $this->getVersion($request, $versionSource, $versionParam);
        $expireDate = config('api.version_expire.'.$version);

        // 版本号检查逻辑
        if (empty($version)) {
            return $this->createErrorResponse(lang('request.api_version_required'), 400);
        }
        if (!in_array($version, config('api.allow_versions', [])) || empty($expireDate)) {
            return $this->createErrorResponse(lang('request.api_version_invalid'), 400);
        }
        if (version_compare($version, config('api.default_version'), '<')) {
            return $this->createErrorResponse(lang('request.api_version_deprecated'), 410);
        }
        if ($expireDate && time() > strtotime($expireDate)) {
            return $this->createErrorResponse(lang('request.api_version_expired'), 403);
        }

        // 将版本号附加到请求对象
        $request->version = $version;
        return $next($request);
    }

    /**
     * 获取API版本号
     *
     * @param mixed $request 请求对象
     * @param string $source 版本号来源(header/param)
     * @param string $param 版本号参数名
     * @return string
     */
    private function getVersion($request, $source, $param)
    {
        $version = $source === 'header'
            ? $request->header($param)
            : $request->param($param);

        return $version ?: config('api.default_version', 'v1');
    }

    /**
     * 创建错误响应
     *
     * @param string $message 错误信息
     * @param int $code 错误码
     * @return Response
     */
    private function createErrorResponse($message, $code): Response
    {
        return Response::create([
            'code' => $code,
            'message' => $message,
            'data'    => null,
            'timestamp' => time()
        ], 'json', 401)->header(['Content-Type' => 'application/json']);
    }
}
